Prototype 使用讓喜歡物件導向風格的開發者可以更接近使用物件導向功能,但需要注意一些可能造成的幽微問題,並有可能在新版本的JS裡面,protype 客製功能以新功能被實現時,產生差異。
另,實體化問題也是需要注意的部分。new 的使用尚若忽略宣告,會導致該函式以一般函式的身份進行呼叫,而不是以建構式的身份,於是不會建立新物件。JS 新手可能會掉入試著呼叫建構式卻沒加上 new 的情況,不僅會導致會預期的錯誤,也將會出現細微難辨的效果。
在每個 DOM 元素的 prototype 加入功能
HTMLElement.prototype.shout = function(){
console.log("hello");
}
ƒ (){
console.log("hello");
}
var a = document.querySelector("a");
undefined
a.shout()
VM885:2 hello
Object.prototype.keys = function(){
var keys = [];
for (var p in this)
//keys.push(p); //會造成所有物件都綁定
if (this.hasOwnProperty(i)) keys.push(i); //改寫增加判斷是不是實體化過的
return keys;
}
var obj = {a: 1, b: 2, C; 3};
obj.keys().length == 3
Number.prototype.add = function(num){
return this+ num;
}
var n = 5;
n.add(3);
(5).add(3);
5.add(3); //發生錯誤
function MyArray() {}
MyArray.prototype = new Array();
var mine = new MyArray();
mine.push(1, 2, 3);
//模擬 Array 功能但並非真正的子類別
function MyArray() {}
MyArray.prototype.length = 0;
(function(){
var methods = ['push', 'pop', 'shift', 'unshift', 'slice', 'splice', 'join'];
for (var i = 0; i < methods.length; i++) (function(name) {
MyArray.prototype[name] = function() {
return Array.prototype[name].apply(this, arguments);
}
})(methods[i])
})();
var mine = new MyArray();
var mine = new MyArray();
mine.push(1, 2, 3);
沒有使用 new 直接對全域變數造成污染。
function User(first, last){
this.name = first + " " + last;
}
var name = "test"
var user = User("Ichigo", "Kuroaki")
console.log(name === "test") //false
var Person = Object.subClass({
init: function(isDancing) {
this.dancing = isDancing;
},
dance: function() {
return this.dancing;
}
})
var Ninja = Person.subClass({
init: function(isDancing) {
this._super(false);
},
dance: function() {
return this._super();
},
sqingSword: function() {
return true;
}
})
var person = new Person(true);
console.log(person.dance())
var ninja = new Ninja();
console.log(ninja.sqingSword())
console.log(ninja instanceof Person)
(function(){
var initializing = false,
superPattern = /xyz/.test(function(){ xyz }) ? /\b_super\b/ : /.*/;
Object.subClass = function(properties) {
var _super = this.prototype;
initializing = true;
var proto = new this();
initializing = false;
for (var name in properties) {
proto[name] = typeof properties[name] == "function" && typeof _super[name] == "function" && superPattern.test(properites[name]) ? (function(name, fn) {
return function() {
var tmp = this._super;
this._super = _super[name];
var ret = fn.apply(this, arguments);
this._super = tmp;
return ret;
}
})(name, properties[name]) :
properties[name];
}
function Class() {
if(!initializing && this.init)
this.init.apply(this, arguments);
}
Class.prototype = proto;
Class.constructor = Class;
Class.subClass = arguments.calle;
return Class;
}
})();
Any fool can write code that a computer can understand. Good programmers write code that humans can understand. – Martin Fowler
https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Inheritance_and_the_prototype_chain